package ru.dc;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import ru.dc.object.SearchRequest;
import ru.dc.object.Settings;
import ru.dc.object.UserInfo;
import ru.dc.object.commands.*;

import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

/**
 * <pre>
 * User: Penkov Vladimir
 * Date: 08.10.2010
 * Time: 16:06:43
 * </pre>
 */
public class HubConnection extends Connection {

    private String key;
    private Log logger = LogFactory.getLog(getClass());
    private String assignedAddress;
    private String name;
    private String topic;
    private Set<UserInfo> users = new HashSet<UserInfo>();


    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getAssignedAddress() {
        return assignedAddress;
    }

    public void setAssignedAddress(String assignedAddress) {
        this.assignedAddress = assignedAddress;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getTopic() {
        return topic;
    }

    public void setTopic(String topic) {
        this.topic = topic;
    }

    public void search(SearchRequest request) {
        Settings settings = Application.getApplication().getSettings();

        Search search = new Search();
        search.setActive(getServerInfo().isActive());
        search.setAddress(settings.isGetAddressFromHub() ? getAssignedAddress() : settings.getExternalAddress());
        search.setPort(Application.getApplication().getExternalListener().getPort());
        search.setDataType(request.getDataType());
        search.setRequestorNick(getServerInfo().getNick());
        search.setSizeRestricted(request.isSizeRestricted());
        search.setSize(request.getSize());
        search.setMaxSize(request.isMaxSize());
        search.setSearchPattern(request.getQuery());
        sendCommand(search);
    }

    public void chat(String message) {
        ChatCommand command = new ChatCommand();
        command.setNick(getServerInfo().getNick());
        command.setText(message);
        sendCommand(command);
    }

    public void privateChat(String targetNick, String message) {
        To to = new To();
        to.setTargetNick(targetNick);
        to.setSourceNick(getServerInfo().getNick());
        to.setSenderNick(getServerInfo().getNick());
        to.setMessage(message);

        sendCommand(to);
    }

    /**
     * Отправляет удаленному пользователю запрос на открытие соединения на стороне удаленного клиента.
     * @param nick ник пользователя
     */
    public void askForPassiveConnection(String nick) {
        if (getServerInfo().isActive()) {
            return;
        }

        RevConnectToMe cmd = new RevConnectToMe();
        cmd.setClientNick(getServerInfo().getNick());
        cmd.setTargetNick(nick);
        sendCommand(cmd);
    }

    /**
     * Отправляет удаленному пользователю запрос подключение к локальному клиенту.
     * @param nick ник пользователя
     */
    public void askForActiveConnection(String nick) {
        if (!getServerInfo().isActive()) {
            return;
        }

        ConnectToMe cmd = new ConnectToMe();
        cmd.setSenderNick(getServerInfo().getNick());
        cmd.setNick(nick);
        cmd.setAddress(getAssignedAddress());
        cmd.setPort(Application.getApplication().getSettings().getTcpPort());
        sendCommand(cmd);
    }

    public void addUser(UserInfo user) {
        users.add(user);
    }

    public void removeUser(UserInfo user) {
        users.remove(user);
    }

    public void removeUser(String nick) {
        Set<UserInfo> toRemove = new HashSet<UserInfo>();
        for (UserInfo userInfo : users) {
            if (userInfo.getNick().equals(nick)) {
                toRemove.add(userInfo);
            }
        }
        users.removeAll(toRemove);
    }

    public Set<UserInfo> getUsers() {
        return Collections.unmodifiableSet(users);
    }

    public UserInfo findUser(String nick) {
        for (UserInfo user : users) {
            if (user.getNick().equals(nick)) {
                return user;
            }
        }
        return null;
    }

    @Override
    public void reconnect() throws IOException {
        setName(null);
        setTopic(null);
        setAssignedAddress(null);
        setKey(null);
        users.clear();
        super.reconnect();
    }
}
